--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
scripts/create-offline-bundle.sh v4.7.0-rc.2 (a20c7e1c) Text, 4.55 KB
T8b949e#!/usr/bin/env bash
Tffa657set -euo pipefail
usageTff7b72(Tff7b72) Tff7b72{
cat Ta5d6ff<<'EOF'
Create an offline bundle for air-gapped (zero-network) builds.
This script downloads and caches everything needed to build MeshChatX without
any network access. Run it on an online machine, then transfer the resulting
vendor/offline/ directory to your air-gapped build host.
Usage:
bash scripts/create-offline-bundle.sh [options]
Options:
--warm-packaging Pre-download electron-builder packaging tools
(appimagetool, app-builder, etc.) by running a
dummy Linux build. Increases bundle size.
--out-dir PATH Output directory (default: vendor/offline)
-h, --help Show this help
Prerequisites on the online machine:
- pnpm (matching packageManager in package.json)
- uv
- Node.js >= 24
- Python >= 3.11
The bundle includes:
- node_modules/ (fully resolved, with all postinstall artifacts)
- uv cache (all Python wheels)
- electron-builder cache (app-builder and related tools)
- Verification that all vendored assets are present
On the air-gapped machine:
bash scripts/install-offline.sh
MESHCHATX_OFFLINE_BUILD=1 make build
EOF
Tff7b72}
Te6edf3ROOT_DIRTff7b72=Ta5d6ff"Tff7b72$(Tffa657cd Ta5d6ff"Tff7b72$(dirname Ta5d6ff"Tffd700${Te6edf3BASH_SOURCETb4b4b4[0]Tffd700}Ta5d6ff"Tff7b72)Ta5d6ff/..Ta5d6ff" Tff7b72&& Tffa657pwdTff7b72)Ta5d6ff"
Tffa657cd Ta5d6ff"Tffd700${Te6edf3ROOT_DIRTffd700}Ta5d6ff"
Te6edf3WARM_PACKAGINGTff7b72=Ta5d6ff"0"
Te6edf3OUT_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3ROOT_DIRTffd700}Ta5d6ff/vendor/offlineTa5d6ff"
Tff7b72while Tff7b72[Tff7b72[ Te6edf3$# -gt T79c0ff0 Tff7b72]Tff7b72]Tb4b4b4; Tff7b72do
Tff7b72case Ta5d6ff"Te6edf3$1Ta5d6ff" Tff7b72in
--warm-packagingTff7b72)
Te6edf3WARM_PACKAGINGTff7b72=Ta5d6ff"1"
Tffa657shift
Tb4b4b4;Tb4b4b4;
--out-dirTff7b72)
Te6edf3OUT_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --out-dirTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--Tff7b72)
Tffa657shift
Tb4b4b4;Tb4b4b4;
-hTb4b4b4|--helpTff7b72)
usage
Tffa657exit T79c0ff0
Tb4b4b4;Tb4b4b4;
*Tff7b72)
Tffa657echo Ta5d6ff"Ta5d6ffUnknown argument: Te6edf3$1Ta5d6ff" >Tb4b4b4&T79c0ff2
usage
Tffa657exit T79c0ff1
Tb4b4b4;Tb4b4b4;
Tff7b72esac
Tff7b72done
require_cmdTff7b72(Tff7b72) Tff7b72{
Tff7b72if ! Tffa657command -v Ta5d6ff"Te6edf3$1Ta5d6ff" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffMissing required command: Te6edf3$1Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tff7b72}
require_cmd node
require_cmd pnpm
require_cmd uv
require_cmd python3
Te6edf3VERSIONTff7b72=Tff7b72$(node -p Ta5d6ff"require('./package.json').version"Tff7b72)
Te6edf3PLATFORMTff7b72=Tff7b72$(uname -s Tb4b4b4| tr Ta5d6ff'[:upper:]' Ta5d6ff'[:lower:]'Tff7b72)
Te6edf3ARCHTff7b72=Tff7b72$(uname -mTff7b72)
Te6edf3BUNDLE_NAMETff7b72=Ta5d6ff"Ta5d6ffmeshchatx-offline-bundle-Tffd700${Te6edf3VERSIONTffd700}Ta5d6ff-Tffd700${Te6edf3PLATFORMTffd700}Ta5d6ff-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff"
Te6edf3BUNDLE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff/Tffd700${Te6edf3BUNDLE_NAMETffd700}Ta5d6ff"
rm -rf Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff"
mkdir -p Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"==> [1/7] Verifying lockfiles..."
Tff7b72if Tff7b72[Tff7b72[ ! -f Ta5d6ff"pnpm-lock.yaml" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Missing pnpm-lock.yaml. Run 'pnpm install' first." >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tff7b72if Tff7b72[Tff7b72[ ! -f Ta5d6ff"uv.lock" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Missing uv.lock. Run 'uv lock' first." >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tffa657echo Ta5d6ff"==> [2/7] Ensuring vendored assets..."
node scripts/fetch-micron-wasm.mjs
python3 scripts/build/fetch_reticulum_manual.py
python3 scripts/build/fetch_repository_wheels.py
Tffa657echo Ta5d6ff"==> [3/7] Installing Node.js dependencies..."
pnpm install --frozen-lockfile
Tffa657echo Ta5d6ff"==> [4/7] Running postinstall hooks..."
mkdir -p Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/electron-builder-cacheTa5d6ff"
Te6edf3ELECTRON_BUILDER_CACHETff7b72=Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/electron-builder-cacheTa5d6ff" pnpm run electron-postinstall
Tffa657echo Ta5d6ff"==> [5/7] Bundling node_modules..."
Tff7b72if tar --help T79c0ff2>/dev/null Tb4b4b4| grep -q -- Ta5d6ff'--hard-dereference'Tb4b4b4; Tff7b72then
tar czf Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/node_modules.tar.gzTa5d6ff" --hard-dereference node_modules/
Tff7b72else
Te6edf3NM_BUNDLETff7b72=Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/node_modules-bundleTa5d6ff"
cp -rL node_modules Ta5d6ff"Tffd700${Te6edf3NM_BUNDLETffd700}Ta5d6ff"
Tff7b72(Tffa657cd Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff" Tff7b72&& tar czf node_modules.tar.gz node_modules-bundle/Tff7b72)
rm -rf Ta5d6ff"Tffd700${Te6edf3NM_BUNDLETffd700}Ta5d6ff"
Tff7b72fi
Tffa657echo Ta5d6ff"==> [6/7] Installing Python dependencies and populating uv cache..."
mkdir -p Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/uv-cacheTa5d6ff"
Te6edf3UV_CACHE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/uv-cacheTa5d6ff" uv sync --group dev
Tffa657echo Ta5d6ff"==> [7/7] Finalizing..."
Tff7b72if Tff7b72[Tff7b72[ Ta5d6ff"Tffd700${Te6edf3WARM_PACKAGINGTffd700}Ta5d6ff" Tff7b72=Tff7b72= Ta5d6ff"1" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff" Pre-downloading electron-builder packaging tools..."
Te6edf3ELECTRON_BUILDER_CACHETff7b72=Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/electron-builder-cacheTa5d6ff" Tffea00\
npx electron-builder --linux dir --publishTff7b72=never >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1 Tff7b72|| Tffa657true
Tff7b72fi
cat > Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff/.bundle-manifest.jsonTa5d6ff" Ta5d6ff<<EOF
{
"name": "meshchatx-offline-bundle",
"version": "${VERSION}",
"platform": "${PLATFORM}",
"arch": "${ARCH}",
"created": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"warm_packaging": ${WARM_PACKAGING}
}
EOF
Tffa657echo Ta5d6ff""
Tffa657echo Ta5d6ff"Ta5d6ffOffline bundle created: Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff""
ls -lh Ta5d6ff"Tffd700${Te6edf3BUNDLE_DIRTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff""
Tffa657echo Ta5d6ff"To transfer to an air-gapped machine:"
Tffa657echo Ta5d6ff"Ta5d6ff tar czf meshchatx-offline-Tffd700${Te6edf3PLATFORMTffd700}Ta5d6ff-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff.tar.gz -C Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff Tffd700${Te6edf3BUNDLE_NAMETffd700}Ta5d6ff"
Tffa657echo Ta5d6ff""
Tffa657echo Ta5d6ff"On the air-gapped machine:"
Tffa657echo Ta5d6ff"Ta5d6ff tar xzf meshchatx-offline-Tffd700${Te6edf3PLATFORMTffd700}Ta5d6ff-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff.tar.gzTa5d6ff"
Tffa657echo Ta5d6ff" bash scripts/install-offline.sh"
Tffa657echo Ta5d6ff" MESHCHATX_OFFLINE_BUILD=1 make build"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────